/**
* @file Hashtable.h Hashtable Template Class.
*
*/

/*
 *  hashtable.h
 *  Hashtable
 *
 *  Created by Christoph Ehscheidt on 05.06.07.
 *	Modified by Andy Albert Fuchs
 *
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */
#ifndef _HASHTABLE_
#define _HASHTABLE_

#include "List.h"
#include <math.h>
#include <assert.h>

using namespace std;

class HashtableException {
public:
	char* msg;

	HashtableException(char* msg) {
		this->msg = msg;
	}
};

template <class type>
class Hashtable {
	double min, max;
	int size;
	int usedSize;
	int elements;
	
	List<type>* table;
	
	/**
	* Reorganize the hashtable.
	* @param tablesize new Size of table
	*
	*/
	void reorganize(int tablesize);

	/**
	*	Compares two keys and give a boolean back, if equal or not.
	*	@param key1 pointer for lexem1
	*	@param key2 pointer for lexem2
	*/
	bool isEqualKey(char* key1, char* key2);

public:
	Hashtable();	
	Hashtable(double min, double max);

	~Hashtable();

	/**
	* Calculates a hashcode for a string key 
	* @return hashcode
	*/
	static int getHashcode(char* key, int length);
	
	/**
	* Insert a (hashcode,element) tuple into the hashtable.
	* @param hashcode	hashcode as string
	* @param element	element
	*/
	void put(int hashcode, type* element);

	/**
	* Calculates how much the table is filled.
	* @return double Percentage
	*/
	double filledPercentage();
	
	/**
	* Checks if a key already exists.
	* @param key			key as string
	* @param lexemLength	length of the lexem
	* 
	* @return				bool, true if key exists
	*/
	bool keyExists(char* key, int lexemLength);
	
	/**
	* Get the value for a key.
	* @param key key as string.
	* @return type value related to the key
	*/
	type* get(char* key, int lexemLength);

	int countCollisions();
	
	int getSize();
	
	/**
	* Removes an Element of the hashtable
	* @param key Key
	* @param element Value
	* @return bool True if removal had success
	*/

	/*
	bool remove(char* key, type element)  {
	
		List<Element >* list = &this->table[ this->hashcode(key) % this->size];
		
		List<Element >::Iterator iter = list->begin();  // WARUM?! (MS Studio kann es!)
		bool done = false;
		while(iter != list->end()) {
			char* keyOfCurrentElement = (*iter)->getKey();

			// Don't forget to overload == Operator in SymtableEntry
			if(isEqualKey(key, keyOfCurrentElement) && (*iter)->getData() == element) {
				done = list->remove(&iter);
				
				// correcting counters
				if(done) {
					this->elements--;
					
					if(list->isEmpty()) {
						this->usedSize--;
					}
				} else {
					throw HashtableException("Removing failed!");
				}
				break;
			}
			iter++;
		}
		
		// check if we are too big
		if(this->filledPercentage() < this->min) {
			//make it smaller
			this->reorganize(this->size/2);
		}
	
		return done;
	}
	*/
	
	/**
	* Prints the complete hashtable on cout
	*/
	void print();
	
	/**
	* Sets the maximum limit of the used size
	* @param max Value (percent)
	*/
	void setMax(double max);

	double getMax();
	
	/**
	* Sets the minimum limit of the used size
	* @param min Value (percent)
	*/
	void setMin(double min);

	List<type>* getTable();
};

#endif
